package cn.ibizlab.util.helper.typehandler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import cn.ibizlab.util.security.SpringContextHolder;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes({String.class})
public class EncryptTypeHandler extends BaseTypeHandler<String> {

    public static String getEncryptStringKey(){
        return SpringContextHolder.getApplicationContext().getEnvironment().getProperty("ibiz.typehandler.encryptkey", "ibzkeys123456789");
    }
    public static byte[] getEncryptByteKey(){
        String keys =EncryptTypeHandler.getEncryptStringKey();
        return keys.getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        if(StringUtils.hasLength(parameter)){
            AES aes = SecureUtil.aes(getEncryptByteKey());
            String encrypt = aes.encryptHex(parameter);
            ps.setString(i, encrypt);
        }else{
            ps.setString(i, null);
        }
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return decrypt(rs.getString(columnName));
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return decrypt(rs.getString(columnIndex));
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return decrypt(cs.getString(columnIndex));
    }

    public String decrypt(String value){
        if(StringUtils.hasLength(value)){
            return SecureUtil.aes(getEncryptByteKey()).decryptStr(value);
        }
        return null;
    }
}
